/**
 * Novel领域类。提供小说的下载、删除及加载信息功能
 */
"use strict";
var path = require("path");
var http = require('http');
var cheerio = require("cheerio");
var iconv = require('iconv-lite');
var BufferHelper = require('bufferhelper');
var fs = require("fs");
var entities = require("entities");
class Novel {
    constructor() {
        this._name = "";//小说名，根据url内容初始化
        this._chapters = 0;//章节数，根据url内容初始化
        this._url = "";//下载地址
        this._directory = "";//保存小说的目录，默认是download目录下，以小说名为目录名
        this._detailDir = "";//章节页面保存目录
        this.chapterSet = new Set();
        this.running = 0;
        this.limit = 9;
    };
    get name() {
        return this._name;
    };
    get chapters() {
        return this._chapters;
    };
    get directory() {
        return this._directory;
    };
    set directory(dir) {
        this._directory = dir;
        this._detailDir = dir + "/pages";
    };
    //从指定URL下载,并返回结果
    /**
     * afterDownload:function(err,novel)
     * progress:function(completeCount)
     * beforeDownload:function(err,novel)
     */
    downloadFrom(url,beforeDownload,progress,afterDownload) {
        let me = this;
        me._url = url;
        http.get(url, function (res) {
            let bufferHelper = new BufferHelper();
            res.on('data', function (chunk) {
                bufferHelper.concat(chunk);
            });
            res.on("end", function () {
                let indexPage = iconv.decode(bufferHelper.toBuffer(), 'gbk');
                me.parseChapters(indexPage);
                beforeDownload(null, me);
                me.readyDownload(progress,afterDownload);
            });
        });
    };
    //从指定目录加载信息
    static loadFromDirectory(directory) {
        let result = new Novel();
        result._directory = directory;
        result._detailDir = directory + "/pages";
        result._name = path.basename(directory);
        let pages = fs.readdirSync(result._detailDir);
        result._chapters = pages.length;
        return result;
    };
    //删除
    /**
     * callfack ：function(err,msg)
     */
    delete(callback) {
        let me = this;
        fs.readdir(me._detailDir, function (err, files) {
            if (files.length != undefined) {
                for (var i = 0; i < files.length; i++) {
                    fs.unlinkSync(me._detailDir +"/"+ files[i]);
                }
            }
            fs.rmdirSync(me._detailDir);
            fs.unlinkSync(me._directory + "/index.html");
            fs.rmdir(me._directory, function (err) {
                if (err) {
                    callback(err);
                } else {
                    callback(null, me._name + "已删除");
                }
            });
        });
    };
    parseChapters(indexPage) {
        let me = this;
        let cio = cheerio.load(indexPage);
        let fileIndex = 1;
        me._name = cio("dd>h1").first().text().split(" ")[0];
        me._directory = "./download/" + me._name;
        me._detailDir = me._directory + "/pages";
        cio("td.L").each(function (i, e) {
            let item = cio(e).children("a").last();
            let title = item.text();
            if (item != undefined && title != undefined && title != "") {
                let link = item.attr("href");
                me.chapterSet.add({
                    "title": title,
                    "link": me._url + link,
                    "index": fileIndex
                });
                fileIndex++;
                me._chapters++;
            }
        });
    };
    readyDownload(progress,afterDownload) {
        let me = this;
        fs.exists(me.directory, function (flag) {
            if (!flag) {
                fs.mkdirSync(me.directory);
            };
            //generate index.html
            let indexfile = me.generateIndexfile();
            fs.writeFile(me.directory + "/index.html", indexfile, { encoding: "utf8" }, function (err) {
                if (err) {
                    console.log(err.message);
                }
            });
            //mkdir pages in novelName directory
            fs.exists(me._detailDir, function (eFlag) {
                if (!eFlag) {
                    fs.mkdirSync(me._detailDir);
                };
                me.downloadAll(progress,afterDownload);
            });
        })
    };
    /**
     * 下载所有章节
     */
    downloadAll(progress,afterDownload) {
        let me = this;
        if (me.chapterSet.size == 0) {
            return;
        }
        for (let temp of me.chapterSet) {
            if (me.running < me.limit && me.chapterSet.size > 0) {
                me.download(temp, function (err) {
                    if (err) {
                        afterDownload(err,me);
                    } else {
                        me.running--;
                        me.chapterSet.delete(temp);
                        progress(me.chapters - me.chapterSet.size);
                        if (me.chapterSet.size > 0) {
                            me.downloadAll(progress,afterDownload);
                        } else {
                            afterDownload(null, me);
                        }
                    }
                });
            }
        }
    };
    generateIndexfile() {
        let me = this;
        let result = ["<!DOCTYPE html><html><head><meta charset='utf-8'/></head>", "<body><center><h1>" + me._name + "</h1></center><table>"];
        let i = 0;
        let j = 1;
        result.push("<tr>");
        for (let item of me.chapterSet) {
            result.push("<td><a href='pages/" + (i + 1) + ".html'>" + item.title + "</a></td>");
            if (j % 5 == 0) {
                result.push("</tr>");
                result.push("<tr>");
            }
            j++;
            i++;
        };
        result.push("</table></body></html>");
        return result.join("\n");
    };
    download(item, callback) {
        let me = this;
        me.running++;
        let url = item.link;
        let pagename = item.index;
        http.get(url, function (res) {
            let bufferHelper = new BufferHelper();
            res.on('data', function (chunk) {
                bufferHelper.concat(chunk);
            });
            res.on("end", function () {
                let contentPage = iconv.decode(bufferHelper.toBuffer(), 'gbk');
                let cio = cheerio.load(contentPage);
                let content = entities.decode(cio("#contents").html());
                let prePage = pagename == 1 ? 1 : pagename - 1;
                let nextPage = pagename + 1;
                let title =`<center>第${item.index}章 ${item.title}</center><br/>`;
                let pages = "<center><a href='" + prePage + ".html'>Prev</a>&nbsp;&nbsp;<a href='" + nextPage + ".html'>Next</a> &nbsp;&nbsp;<a href='../index.html'>catalog</a></center><br/>";
                let targetHtml = "<!DOCTYPE html><html><head><meta charset='utf-8'/><script type='text/javascript'>function keypress(){var keycode=window.event.keyCode;switch(keycode){case 106:window.location='" + prePage + ".html';break;case 107:window.location='" + nextPage + ".html';break;case 104:window.location='../index.html';break;}}</script></head><body onkeypress='keypress()'>" +title+ pages + content;
                targetHtml += pages;
                targetHtml += "</body></html>";
                fs.writeFile(me._detailDir+ "/" + pagename + ".html", targetHtml, { encoding: "utf8" }, function (err) {
                    callback(err);
                });
            });
        }).on("error", function (e) {
            console.log(e + ":" + item);
        });
    }
}
exports.Novel = Novel;